<?php
namespace Util\AliPay;

use Mall\Framework\Core\ResultWrapper;
use Mall\Framework\Core\ErrorCode;

use Util\AliPay\Sign;

class Mini extends Sign
{
    /**
     * 支付宝分配给开发者的应用ID
     */
    private $appid;

    /**
     * 公共的接口请求地址
     * @var string
     */
    private $gatewayUrl = 'https://openapi.alipay.com/gateway.do';

    public function __construct($appid, $rsaPrivateKeyFilePath, $rsaPrivateKey)
    {
        $this->appid = $appid;
        parent::__construct($rsaPrivateKeyFilePath, $rsaPrivateKey);
    }

    /**
     * 换取授权访问令牌
     * 官网地址: https://opendocs.alipay.com/apis/api_9/alipay.system.oauth.token
     */
    public function token($code, $returnUserId = false)
    {
        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.system.oauth.token',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
            'grant_type' => 'authorization_code',
            'code'       => $code,
        ];

        ksort($params);
        // 生成签名
        $params['sign'] = parent::sign($params);
        foreach ($params as &$value) {
            $value = $this->characet($value, $params['charset']);
        }

        $reponse = request($this->gatewayUrl,$params);
        $return = self::commonReust($reponse, $params['method']);

        if($returnUserId){
            return ResultWrapper::success(getArrayItem($return, 'user_id', 0));
        }

        return ResultWrapper::success($return);
    }

    /**
     * 开启代商户签约、创建应用事务
     * 官网地址: https://opendocs.alipay.com/apis/api_50/alipay.open.agent.create
     */
    public function agentCreate($account, $shopData)
    {
        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.open.agent.create',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
        ];

        // 获取业务请求参数集合
        $return = self::getAgentCreateBizContent($account, $shopData);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();
        $params['biz_content'] = $biz_content;

        $requestUrl = self::createRquestUrl($params);

        $reponse = request($requestUrl,['biz_content' => $biz_content]);
        $return = self::commonReust($reponse, $params['method']);
        return ResultWrapper::success($return);
    }

    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getAgentCreateBizContent($account, $shopData)
    {
        $bizcontent = [
            'account'        => $account, // isv代操作的商户账号，可以是支付宝账号，也可以是pid（2088开头）
            'contact_info'   => [
                'contact_name'    => $shopData['contact_name'], // 商户联系人名称
                'contact_mobile'  => $shopData['contact_mobile'], // 商户手机号
            ]
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 代签约产品通用接口
     * 官网地址: https://opendocs.alipay.com/apis/01az5o
     */
    public function commonSign($batch_no, $mcc_code, $product_code, $business_license_pic)
    {
        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.open.agent.common.sign',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',

        ];

        $biz_content = [
            'batch_no'        => $batch_no, // 代商户操作事务编号
            'mcc_code'        => $mcc_code, // 经营类目编码
            'product_code'    => $product_code, // isv要代商户签约产品码
            'business_license_pic' => new \CURLFile(realpath($business_license_pic)), // 营业执照图片。被代创建商户运营主体为个人账户必填，企业账户无需填写
            'long_term'       => true,
        ];

        $requestUrl = self::createRquestUrl( array_merge($params,$biz_content), $biz_content);

        $reponse = request($requestUrl, $biz_content, 40, false, [], false, [], false, false, false); V($reponse);
        $return = self::commonReust($reponse, $params['method']);
        return ResultWrapper::success($return);
    }


    /**
     * 代商户签约，提交信息确认接口
     * 官网地址: https://opendocs.alipay.com/apis/01b0f6
     */
    public function confirm($batch_no)
    {
        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.open.agent.commonsign.confirm',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
        ];


        // 获取业务请求参数集合
        $return = self::getConfirmBizContent($batch_no);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();
        $params['biz_content'] = $biz_content;
        $requestUrl = self::createRquestUrl($params);
        $reponse = request($requestUrl,['biz_content' => $biz_content]);  V($reponse);
        $return = self::commonReust($reponse, $params['method']);
        return ResultWrapper::success($return);
    }

    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getConfirmBizContent($batch_no)
    {
        $bizcontent = [
            'batch_no'        => $batch_no, // 代商户操作事务编号
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 查询申请单状态
     * 官网地址: https://opendocs.alipay.com/apis/api_50/alipay.open.agent.order.query/
     */
    public function agentQuery($batch_no)
    {
        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.open.agent.order.query',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
        ];

        // 获取业务请求参数集合
        $return = self::getAgentQueryBizContent($batch_no);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();
        $params['biz_content'] = $biz_content;

        $requestUrl = self::createRquestUrl($params);

        $reponse = request($requestUrl,['biz_content' => $biz_content]);
        $return = self::commonReust($reponse, $params['method']);
        return ResultWrapper::success($return);
    }

    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getAgentQueryBizContent($batch_no)
    {
        $bizcontent = [
            'batch_no'        => $batch_no, // 代商户操作事务编号
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 向商户发起代运营操作
     * 官网地址: https://opendocs.alipay.com/apis/01ea4v
     */
    public function operation($merchant_no, $alipay_account)
    {
        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.open.sp.operation.apply',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
        ];

        // 获取业务请求参数集合
        $return = self::getOperationBizContent($merchant_no, $alipay_account);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();
        $params['biz_content'] = $biz_content;

        $requestUrl = self::createRquestUrl($params);

        $reponse = request($requestUrl,['biz_content' => $biz_content]); V($reponse);
        $return = self::commonReust($reponse, $params['method']);
        return ResultWrapper::success($return);
    }

    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getOperationBizContent($merchant_no, $alipay_account)
    {
        $bizcontent = [
            'out_biz_no'        => createOrderSn(1,1,1), // 外部操作流水
            'operate_type'      => 'ACCOUNT_BIND',
            'access_product_code' => 'OPENAPI_BIND_DEFAULT',
            'merchant_no'       => $merchant_no,
            'alipay_account'    => $alipay_account,
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 生成请求url
     */
    private function createRquestUrl($params, $biz_content = [])
    {
        // 生成签名
        ksort($params);
        $params['sign'] = parent::sign($params);
        /*foreach ($params as &$value) {
            $value = $this->characet($value, $params['charset']);
        }*/

        // 业务参数和系统参数混在一起的时候，业务参数不参与生成请求url中
        if(!empty($biz_content)){
            foreach ($biz_content as $k => $v) {
                unset($params[$k]);
            }
        }

        //系统参数放入GET请求串
        $requestUrl = $this->gatewayUrl . "?";
        unset($params['biz_content']);
        foreach ($params as $sysParamKey => $sysParamValue) {
            $requestUrl .= "$sysParamKey=" . urlencode($this->characet($sysParamValue, "UTF-8")) . "&";
        }
        $requestUrl = substr($requestUrl, 0, -1);

        return $requestUrl;
    }


    /**
     * 统一的错误处理方法
     */
    public function commonReust($reponse, $methodName)
    {
        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部接口网络错误', ErrorCode::$apiNotResult);
        }

        $reponseContent = json_decode($reponse['content'], true);
        return $reponseContent[str_replace('.','_',$methodName).'_response'];
    }

}